/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package racer.client.gui.entities;

import java.awt.*;
import java.awt.geom.AffineTransform;
import java.awt.geom.Point2D;
import java.awt.image.*;

/**
 *
 * @author Piet
 */
public abstract class Entity {
    //x-coördinaat van de locatie van deze Entity
    protected double x;
    //y-coördinaat van de locatie van deze Entity
    protected double y;
    protected double prevx, prevy;
    protected double ax, ay, vx, vy;
    //huidige horizontale snelheid van deze Entity (pixels/seconde)
    protected double dx = 0;
    //huidige verticale snelheid van deze Entity (pixels/seconde)
    protected double dy = 0;
    protected BufferedImage entImage;
    public Image buf;
    public Graphics gbuf;   
    protected int id,angle;
    protected boolean accelerating, braking, steeringleft, steeringright;
    protected double speedX, speedY;
    
    protected double initX, initY;
    protected int initAngle;

    public Entity(int x, int y, int id) {
        this.x = x;
        this.y = y;
        this.initX = x;
        this.initY = y;
        this.id=id;
		speedX = 10;
		speedY = 10;
        ax = 5.12;
        ay = 5.12;
    }
    public int getId(){
        return id;
    }
    public double getX() {
        synchronized (this) {
            return x;
        }
    }
    
    public void setXY(double x,double y){
        synchronized (this) {
            this.x = x;
            this.y = y;
        }        
    }

    public void setX(double x) {
        synchronized (this) {
            this.x = x;
        }
    }
    
    public double getY() {
        synchronized (this) {
            return y;
        }
    }
    public void setY(double y) {
        synchronized (this) {
            this.y = y;
        }
    }

    public void move(long delta) {
    	prevx = this.x;
    	prevy = this.y;
        //synchronized (this) {
    		if(steeringleft) {
    			if (accelerating)
        			changeAngle(-5);
    			if (braking)
        			changeAngle(5);			
    		}
    		if(steeringright) {
    			if (accelerating)
        			changeAngle(5);
    			if (braking)
    				changeAngle(-5);				
    		}
	        if(accelerating) {
	    		//x += Math.cos(Math.toRadians(angle))*speedX * delta/20000;
				//y += Math.sin(Math.toRadians(angle))*speedY * delta/20000;
	        	x += Math.cos(Math.toRadians(angle))*speedX;
				y += Math.sin(Math.toRadians(angle))*speedY;
	        	//x += delta * speedX / 10000;
	        	//y += delta * speedY / 10000;
	        	/*
	        	vx += ax*delta/1000000000;
	        	vy += ay*delta/1000000000;
	        	x += vx*delta/1000000000 + ax*(delta/1000000000)*(delta/1000000000)/2;
	        	y += vy*delta/1000000000 + ay*(delta/1000000000)*(delta/1000000000)/2;
	        	*/	        	
			}
	    	if(braking) {
				//x -= Math.cos(Math.toRadians(angle))*speedX * delta/20000;
				//y -= Math.sin(Math.toRadians(angle))*speedY * delta/20000;
				x -= Math.cos(Math.toRadians(angle))*speedX;
				y -= Math.sin(Math.toRadians(angle))*speedY;
				//x -= delta * speedX / 10000;
				//y -= delta * speedY / 10000;
	        	/*vx -= ax*delta/1000000000;
	        	vy -= ay*delta/1000000000;
	        	x -= vx*delta/1000000000 - ax*(delta/1000000000)*(delta/1000000000)/2;
	        	y -= vy*delta/1000000000 - ay*(delta/1000000000)*(delta/1000000000)/2;
	        	*/
			}
            /*moveX(delta);
            moveY(delta);*/
        //}
    }
    
    public void setToPreviousPosition() {
    	this.x = prevx;
    	this.y = prevy;
    }

    public void moveX(long delta) {
        x += (delta * dx) / 1000;
    }

    public void moveY(long delta) {
        y += (delta * dy) / 1000;
    }

    public void setHorizontalMovement(double dx) {
        synchronized (this) {
            this.dx = dx;
        }
    }

    public void setVerticalMovement(double dy) {
        synchronized (this) {
            this.dy = dy;
        }
    }

    public double getHorizontalMovement() {
        synchronized (this) {
            return dx;
        }
    }

    public double getVerticalMovement() {
        synchronized (this) {
            return dy;
        }
    }

    
    public void setAngle(int angle){
        this.angle=angle;
        this.angle = this.angle%360;
        if(this.angle < 0)
        	this.angle+=360;
    }
	public void changeAngle(int angle) {
		this.angle += angle;
        this.angle = this.angle%360;
        if(this.angle < 0)
        	this.angle+=360;
	}
    
    public int getAngle(){
        return angle;
    }    

    public int getLength() {
    	return entImage.getHeight();
    }
    public int getWidth() {
    	return entImage.getWidth();
    }

    public boolean getAccelerating() {
    	return this.accelerating;
    }
    public void setAccelerating(boolean accel) {
    	this.accelerating = accel;
    }
    public void setBraking(boolean braking) {
    	this.braking = braking;
    }
    public void setSteeringLeft(boolean b) {
    	this.steeringleft = b;
    }
    public void setSteeringRight(boolean b) {
    	this.steeringright = b;
    }

    public abstract Point2D getMostTopPosition();
    public abstract Point2D getMostBottomPosition();
    public abstract Point2D getMostLeftPosition();
    public abstract Point2D getMostRightPosition();
    public abstract Point2D getTopLeftCornerPosition();
    public abstract Point2D getTopRightCornerPosition();
    public abstract Point2D getBottomLeftCornerPosition();
    public abstract Point2D getBottomRightCornerPosition();
    
    public abstract Shape getShape();
    public abstract void setInitPosition(double x, double y, int angle);
    public abstract void setToInitPosition();
    
    /**
     * tekent de Entity op de meegegeven Graphics context
     */
    /*
    public void draw(Graphics g) {
        synchronized (this) {
           //g.setColor(Color.WHITE);
            //g.fillRect(0, 0, 1024, 768);              
            g.setColor(color);
            g.fillRect((int) x, (int) y, 5, 5);

            
        }
    }*/

    public void drawPic(Graphics g,BufferedImage carpic) {
        synchronized (this) {
            g.drawImage(carpic, (int)x, (int)y, null);            
        }
    }

    public void drawPic(Graphics g) {
        synchronized (this) {
        	Graphics2D g2d = (Graphics2D)g;
        	// creating the AffineTransform instance 
			AffineTransform affineTransform = new AffineTransform();  
			// set the translation to the mid of the component 
			affineTransform.setToTranslation(512-entImage.getWidth()/2,450-entImage.getHeight()/2);
			//affineTransform.setToTranslation(512,450);
			// rotate the image 
			affineTransform.rotate(Math.toRadians(angle), entImage.getWidth()/2, entImage.getHeight()/2); 
			// draw the image using the AffineTransform 
			g2d.drawImage(entImage, affineTransform, null);
            //g.drawImage(entImage, (int)x, (int)y, null);
			
			if(racer.client.gui.Game.debug) {
				g2d.setColor(Color.RED);
	            g2d.drawString("Accelerating: " + accelerating, 20, 20);
	            g2d.drawString("Braking: " + braking, 20, 40);
	            g2d.drawString("Center position: " + (int)x + "  " + (int)y, 20, 60);
	            g2d.drawString("Angle: " + angle, 20, 100);
			}         
        }
    }
    public void drawPic(Graphics g, int x, int y) {
        synchronized (this) {
        	Graphics2D g2d = (Graphics2D)g;
        	// creating the AffineTransform instance 
			AffineTransform affineTransform = new AffineTransform();  
			// set the translation to the mid of the component 
			affineTransform.setToTranslation(x-entImage.getWidth()/2,y-entImage.getHeight()/2);
			// rotate the image 
			affineTransform.rotate(Math.toRadians(angle), entImage.getWidth()/2, entImage.getHeight()/2); 
			// draw the image using the AffineTransform 
			g2d.drawImage(entImage, affineTransform, null);
            //g.drawImage(entImage, (int)x, (int)y, null);      
        }
    }

}
